package com.dq.rbac.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dq.rbac.entity.SysRole;
import com.dq.rbac.entity.SysUser;
import com.dq.rbac.entity.SysUserRole;
import com.dq.rbac.entity.vo.PageBean;
import com.dq.rbac.service.SysRoleService;
import com.dq.rbac.service.SysUserRoleService;
import com.dq.rbac.service.SysUserService;
import com.dq.rbac.utils.ErrorCode;
import com.dq.rbac.utils.JWTUtils;
import com.dq.rbac.utils.SystemConstant;
import com.dq.rbac.vo.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户相关-API
 *
 * @author Dq
 * @since 2022-12-26 12:59:05
 */
@RestController
@RequestMapping("user")
//@CrossOrigin
@Slf4j
public class SysUserController {

    @Resource
    private SysUserService userService;
    @Resource
    private SysUserRoleService userRoleService;

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    private SysRoleService roleService;

    @Value("${avater.prePath}")
    private String avatarImgPrePath;


    @GetMapping("/getUserList")
    @PreAuthorize("hasAuthority('system:user:list')")
    public R getAllUsers(@RequestHeader(name = "token", required = false) String token) {
        if (token == null || "null".equals(token) || token.isEmpty()) {
            return R.error().code(444).message(ErrorCode.NO_PERMISSION.getMsg());
        }
        log.info("token =  {}", token);
        return R.ok().data("userList", userService.list());
    }

    @GetMapping("login")
    public R login() {
        //生成token
        String token = JWTUtils.createToken("123456");
        return R.ok().data("token", token);
    }

    /**
     * 根据id是否提供 来判断添加或者修改
     * 权限：add edit
     *
     * @param sysUser
     * @return
     */
    @PostMapping("save")
    @PreAuthorize("hasAuthority('system:user:add')" + "||" + "hasAuthority('system:user:edit')")
    public R save(@RequestBody SysUser sysUser) {
        if (sysUser.getId() == null) { //添加
            sysUser.setCreateTime(new Date());
            sysUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getPassword()));
            userService.save(sysUser);
            return R.ok().message("用户添加成功");
        }
        //修改
        sysUser.setUpdateTime(new Date());
        boolean success = userService.updateById(sysUser);
        if (success) {
            return R.ok().message("更新成功");
        } else {
            return R.error().message("修改失败");
        }
    }

    /**
     * 修改密码
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/updateUserPwd")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateUserPwd(@RequestBody SysUser sysUser) {
        SysUser currentUser = userService.getById(sysUser.getId());
        if (!bCryptPasswordEncoder.matches(sysUser.getOldPassword(), currentUser.getPassword())) {
            return R.error().message("输入的旧密码错误");
        }
        currentUser.setPassword(bCryptPasswordEncoder.encode(sysUser.getNewPassword()));
        currentUser.setUpdateTime(new Date());
        boolean success = userService.updateById(currentUser);
        if (success) {
            return R.ok().message("密码修改成功，下一次登录生效！");
        } else {
            return R.error().message("修改中断 请联系管理员");
        }
    }

    /**
     * 上传头像
     *
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/uploadAvatar")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R uploadAvatar(MultipartFile file) throws IOException {
        HashMap<String, Object> resultMap = new HashMap<>();
        if (!file.isEmpty()) {
            String originalFilename = file.getOriginalFilename();
            String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
            String preHead = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String newFileName = preHead + fileType;
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File(avatarImgPrePath + newFileName));

            resultMap.put("title", newFileName);
            resultMap.put("url", "image/userAvatar/" + newFileName);
            return R.ok().message("上传成功").data(resultMap);
        }
        return R.error().message("上传失败");
    }

    /**
     * 头像上传至sql
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/updateAvatar")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateAvatar(@RequestBody SysUser sysUser) {
        SysUser currentUser = userService.getById(sysUser.getId());
        currentUser.setUpdateTime(new Date());
        currentUser.setAvatar(sysUser.getAvatar());
        userService.updateById(currentUser);
        return R.ok().message("修改头像成功");
    }

    /**
     * 分页查询
     *
     * @param pageBean
     * @return
     */
    @PostMapping("/list")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R queryList(@RequestBody PageBean pageBean) {
        String query = pageBean.getQuery().trim(); //去除多余空格的查询条件
        Page<SysUser> page = new Page<>(pageBean.getCurrent(), pageBean.getPageSize());
        Page<SysUser> pageResult = userService.page(page, new LambdaQueryWrapper<SysUser>().like(StrUtil.isNotBlank(query), SysUser::getUsername, query));
        List<SysUser> userList = pageResult.getRecords();
        //遍历role设置user的roleList
        for (SysUser user : userList) {
            List<SysRole> userRoleList = roleService.list(
                    new LambdaQueryWrapper<SysRole>()
                            .inSql(SysRole::getId, "select role_id from sys_user_role where user_id = " + user.getId()));
            user.setRoleList(userRoleList);
        }
        //返回分页total
        long total = pageResult.getTotal();
        return R.ok().data("userList", userList).data("total", total);
    }

    /**
     * 根据id查询用户 用于回显修改时的数据
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R queryById(@PathVariable("id") Long id) {
        SysUser sysUser = userService.getById(id);
        return R.ok().data("sysUser", sysUser);
    }

    /**
     * 校验是否重复添加名称
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/checkUserName")
    @PreAuthorize("hasAuthority('system:user:query')")
    public R checkUserName(@RequestBody SysUser sysUser) {
        if (userService.getByUserName(sysUser.getUsername()) == null) { //查询出没有重复名称
            return R.ok();
        }
        return R.error().message("名字重复，请重新输入");
    }

    /**
     * 删除用户及其关联表
     *
     * @param ids
     * @return
     */
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('system:user:delete')")
    @Transactional
    public R delete(@RequestBody Long[] ids) {
        //删除用户表+用户关联表
        userService.removeByIds(Arrays.asList(ids));
        boolean success = userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getUserId, ids));
        if (success) {
            return R.ok().message("删除成功");
        } else {
            return R.error().message("权限不够,删除失败");
        }
    }

    /**
     * 修改用于默认密码
     *
     * @param id
     * @return
     */
    @GetMapping("resetPassword/{id}")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R resetPassword(@PathVariable Long id) {
        SysUser user = userService.getById(id);
        user.setPassword(bCryptPasswordEncoder.encode(SystemConstant.DEFAULT_PASSWORD));
        user.setUpdateTime(new Date());
        userService.updateById(user);
        return R.ok();
    }

    /**
     * 修改状态
     *
     * @param id
     * @param status
     * @return
     */
    @GetMapping("updateStatus/{id}/status/{status}")
    @PreAuthorize("hasAuthority('system:user:edit')")
    public R updateStatus(@PathVariable("id") Long id, @PathVariable("status") String status) {
        SysUser user = userService.getById(id);
        user.setStatus(status);
        user.setUpdateTime(new Date());
        userService.updateById(user);
        return R.ok();
    }

    /**
     * 分配权限
     *
     * @param roleIds
     * @param userId
     * @return
     */
    @PostMapping("grantRole/{userId}")
    @PreAuthorize("hasAuthority('system:user:role')")
    @Transactional
    public R grantRole(@RequestBody Long[] roleIds, @PathVariable("userId") Long userId) {
        if (roleIds.length == 0 || userId == null) {
            return R.error();
        }
        List<SysUserRole> userRoleList = Arrays.asList(roleIds).stream().map(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setUserId(userId);
            sysUserRole.setRoleId(roleId);
            return sysUserRole;
        }).collect(Collectors.toList());
        userRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        userRoleService.saveBatch(userRoleList);
        return R.ok();
    }


    //私密用法
    @GetMapping("resetRootPass")
    public R resetRootPass() {
        SysUser user = userService.getById(1L);
        user.setPassword(bCryptPasswordEncoder.encode(SystemConstant.DEFAULT_PASSWORD));
        userService.updateById(user);
        return R.ok();
    }


    /**
     * Main测试类
     *
     * @param args
     */
    public static void main(String[] args) {

    }
}

